package com.example.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.controller.util.Data;
import com.example.controller.util.RegexUtils;
import com.example.controller.util.SaltMD5Util;
import com.example.domain.PhoneDto;
import com.example.mapper.UserDao;
import com.example.domain.User;
import com.example.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.example.controller.util.RedisConstants.*;

@Service
public class UserImpl extends ServiceImpl<UserDao, User> implements IUserService {
    @Autowired
    UserDao userDao;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public User getOne(String name) {
        LambdaQueryWrapper<User> lwq = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<User> eq = lwq.eq(User::getName, name);
        User user = userDao.selectOne(eq);
        return user;
    }
//      分页查询内容
    @Override
    public IPage<User> getPageUser(Integer page, Integer size) {
        IPage<User> page1 = new Page<>(page, size);
        userDao.selectPage(page1,null);
        return page1;
    }

    @Override
    public Data login(PhoneDto phoneDto, HttpSession session) {
        // 1.校验手机号
        String phone = phoneDto.getPhone();
        if (RegexUtils.isPhoneInvalid(phone)) {
            return new Data(201,"手机格式错误！");
        }
        // 2.校验验证码
        String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);
        String code = phoneDto.getCode();
        if (code == null || !cacheCode.equals(code)) {
            // 3.不一致报错
            return new Data(202,"验证码错误！");
        }
        // 4.一致，根据手机号查询用户
        User user = query().eq("phone", phone).one();
        // 5.判断用户是否存在
        if (user == null) {
            // 6.不存在，调用方法创建用户并保存
            user = createUserWithPhone(phone);
        }
        // 7.保存用户信息到Redis（ key为token）
        // 7.1.生成Token
        String token = UUID.randomUUID().toString(true);
        System.out.println("token值为"+token);
        // 7.2.putAll(map<>)里面的参数是map，此处需要将用户User转为Hash存储
        PhoneDto dto = BeanUtil.copyProperties(user, PhoneDto.class);
        //且使用StringRedisTemplateredis需要转换成的map的各个字段都是String类型！而bean的各个字段类型各不相同
        dto.setCode(code);        //设置code否则为null，报错空指针
        Map<String, Object> userMap = BeanUtil.beanToMap(dto, new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));
        // 7.3.存储
        String tokenKey = LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);
        // 7.4.设置有效期30分钟,但是如果用户在一直访问则必须刷新有效期（用拦截器实现）
        stringRedisTemplate.expire(LOGIN_USER_KEY + token, LOGIN_USER_TTL, TimeUnit.MINUTES);
        // 8.返回Token
        return new Data(200,"登录成功！",token);
    }

    //  新增查重
    @Override
    public User getUser(String name) {
        LambdaQueryWrapper<User> lwq = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<User> eq = lwq.eq(User::getName, name);
        User user = userDao.selectOne(eq);
        return user;
    }

    private User createUserWithPhone(String phone) {
        // 1.创建用户
        User user = new User();
        user.setPhone(phone);
        // 2.保存用户
        save(user);
        return user;
    }
}
